package net.oztoc.servicetester
{
    import com.adobe.serialization.json.JSON;
    
    import flash.events.MouseEvent;
    import flash.utils.getQualifiedClassName;
    
    import mx.collections.ArrayCollection;
    import mx.collections.XMLListCollection;
    import mx.controls.List;
    import mx.controls.TextArea;
    import mx.controls.TextInput;
    import mx.controls.Tree;
    import mx.core.Application;
    import mx.events.ListEvent;
    import mx.rpc.IResponder;
    import mx.rpc.events.FaultEvent;
    import mx.rpc.events.ResultEvent;
    import mx.utils.ObjectUtil;
    import mx.utils.StringUtil;
    
    import net.oztoc.remoteobject.AMFConnection;

    public class ServiceTesterBase extends Application implements IResponder
    {
        public var history:List;

        public var remoteGateway:TextInput;
        public var remoteClass:TextInput;
        public var remoteMethod:TextInput;
        public var remoteParameters:TextArea;

        public var structure:Tree;

        public var output:TextArea;
        
        
        [Bindable]
        public var property:Object;
        
        [Bindable]
        public var properties:ArrayCollection;
        

        public function ServiceTesterBase()
        {
            super();
        }

        override protected function childrenCreated():void
        {
            super.childrenCreated();
            remoteParameters.text=JSON.encode({password: "", login: ""});
        }

        protected function onClickSend(event:MouseEvent):void
        {
            send();
        }

        protected function send():void
        {
            var service:AMFConnection=new AMFConnection();
            service.gateway=remoteGateway.text;
            service.remoteClass=remoteClass.text;
            service.method=remoteMethod.text;
            service.addEventListener(ResultEvent.RESULT, result);
            service.addEventListener(FaultEvent.FAULT, fault);
            var params:*=StringUtil.trim(remoteParameters.text);
            if (params == "")
                params=new Object();
            else
                params=JSON.decode(params);
            service.send(params);
        }

        public function result(data:Object):void
        {
            output.text=ObjectUtil.toString(data.result);
            
            updateStructure(data.result, "result");
        }

        public function fault(info:Object):void
        {
            output.text=ObjectUtil.toString(info);

            
            updateStructure(info);
        }
        
        
        
		/**
		 * 
		 * @param event
		 **/
		protected function updateStructure(data:*, name:String=""):void
		{
            var declarations:XML = toXML(data, name);
            
            structure.dataProvider = declarations; 
            
            structure.invalidateList();
            
            for (var i:int = 0; i < structure.dataProvider.length; i ++){
                var node:* = structure.dataProvider[i];
                structure.validateNow();
                structure.expandChildrenOf(node, true) 
            } 
            
            structure.selectedIndex = 0;
            
            structure_changeHandler(null);
            
		}

       
        
		/**
		 * 
		 * @param event
		 **/
		protected function structure_changeHandler(event:ListEvent):void
		{
			property = structure.selectedItem;
            
            var props:Array = [];
            
            props.push({label:"name", value:property.@name});
            props.push({label:"type", value:property.@type});
            props.push({label:"value", value:property.@value});
            
            properties = new ArrayCollection(props);
            
		}
        

/*
           private function encode(target:*, source:Object):void
           {
           for (var i:uint=0; i < source.length; i++)
           {
           var group:XML=<group/>;



           group.@id=source[i].id;
           group.@title=source[i].title;

           if (source[i].hasOwnProperty("groups"))
           {
           encode(group, source[i].groups);
           }

           target.appendChild(group);
           }
           }
         */

        /**
         * Returns an XML representation of the object.
         * */
        public function toXML(target:*, name:String="", addClassDefinition:Boolean=true):XML
        {
            var className:String=getQualifiedClassName(target).split("::")[1];

            var nodeName:String=name != "" ? name : className;

            var xmlOutput:XML=<property/>; //new XML("<" + nodeName + "/>");

            xmlOutput.@name=nodeName;
            xmlOutput.@type=className;

            if( ObjectUtil.isSimple(target) )
            {
                xmlOutput.@value = target.toString();
                
                return xmlOutput;
            }
            
            var classInfo:Object=ObjectUtil.getClassInfo(target);
            
            xmlOutput.@type = classInfo.name;
            
            var properties:Array=classInfo.properties;
            var prop:*;

            for each (var qname:QName in properties)
            {
                prop=target[qname.localName];

                trace (qname.localName);
                
                if (ObjectUtil.isSimple(prop) == true && !(prop is Array))
                {
                    xmlOutput.appendChild(buildDeclaration(qname.localName, prop));
                }
                else
                {
                    trace (prop is Array);
                    
                    if (!(prop is Array) && qname.localName != "currentTarget" && qname.localName != "target" && prop!=null)
                    {
                        xmlOutput.appendChild(toXML(prop, qname.localName.toString()));
                    }
                    else if ( prop is Array)
                    {
                        var d:XML = buildDeclaration(qname.localName, prop, true);
                        for (var i:uint = 0; i < prop.length; i++)
                        {
                            d.appendChild(   toXML(prop[i], "[" + i + "]" ) );
                        }
                        
                        xmlOutput.appendChild(d);
                    }
                }
            }

            return xmlOutput;
        }

        private function buildDeclaration(name:String, prop:*, ommitValue:Boolean=false):XML
        {
            var declaration:XML=<property/>;
            declaration.@name=name;
            declaration.@type=typeof(prop);
            
            declaration.@value= ommitValue ? "" : prop;

            return declaration;
        }

    }
}

